/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SAMPLESSET_H__
#define __SAMPLESSET_H__

#include "EvolutiveLib.h"
#include "Data.h"
#include <string>
#include <fstream>
#include <vector>
#include "Detector.h"

using namespace std;
namespace Evolutive {

	//! Class to store BG regions and extra information
	class EVOLUTIVELIB_API CBGRect
	{
	public:
		CvRect Region;
		bool Used;
		int FileIdx;
	};

	//! Class to store a vector of strings
	class EVOLUTIVELIB_API CStrVector : public std::vector<string>{};

	//! Class to store a vector of CBGRegions
	class EVOLUTIVELIB_API CBGRegVector : public std::vector<CBGRect>{};

	//! Create a type for the index vector
	typedef vector<unsigned int> IdxVector;

	//! Define an iterator
    typedef IdxVector::iterator IdxVectorIt;

	//! Class that encodes an images samples set. It allows store and use a labeled set of images.
	class EVOLUTIVELIB_API CSamplesSet
	{
		//! Methods
	public:
		//! Default constructor		
		CSamplesSet(void);
		
		//! Default destructor
		virtual ~CSamplesSet(void);		

#ifdef USE_OPENCV
		//! Assign an expected value to a sample
		void SetExpectedValue(unsigned int Idx,double Value);

		//! Assign an expected value to a set of sample
		void SetExpectedValue(unsigned int IdxFirst,unsigned int IdxLast,double Value);

		//! Load a samples set from disc
		void Load(string FileName);

		//! Save the samples to the disk
		void Save(string FileName);

		//! Show all the images
		void Show(int WaitTime=0,int WndType=0);

		//! Returns the number of samples
		int GetNumSamples(void);

		//! Get samples size
		CvSize GetSamplesSize(void);

		//! Returns the color information
		bool GetColorInfo(void);

		//! Operators overload
		virtual CData* operator[] (unsigned int Idx);

		//! Returns a pointer to a data structure
		virtual CData* GetData(unsigned int Idx);

		//! Returns a pointer to the image
		IplImage *GetImage(unsigned int Idx);
		
		//! Returns the expected value for a certain sample
		double ExpectedVal(unsigned int Idx);

		//! Load the images
		void LoadImages(int NumClasses,string FileName[],double ClassValue[],int Width,int Height);
		void LoadImages(string ImgFileName,string LabelFileName,int Width,int Height);
		void LoadImages(string ObjectFile,string BGFile,int NumNeg,int Width,int Height);

		//! Split the data into train and test
		virtual void SplitData(CSamplesSet *Train,CSamplesSet *Test,double TestPer);

		//! Create a sample set by adding to existing samples set
		virtual void MergeData(CSamplesSet *Samples1,CSamplesSet *Samples2);

		//! Calculate the normalization factor using the fast lighting correction algorithm
		virtual double GetNormFactor(unsigned int Idx)
		{
			return 1.0;
		}

		//! Check if the sample set is binary and return the number of positive and negative samples
		bool GetBinaryDist(int &NumPos,int &NumNeg);

		//! Change the well classified negative samples
		virtual void UpdateSamples(CClassifier *Classifier);

		//! Load the list of BG Images from a file
		void LoadBGFiles(string FileName);

		//! Remove all the BG files
		void ResetBGFiles(void);

		//! Assigns a detector to the samples set
		void SetDetector(CDetector *Detector);
	
	protected:		
		//! Save or recover the data to/from a file
		virtual void Serialize(std::fstream &fs,bool Saving);

		//! Count the number of images of a certain file
		int GetNumImagesFromFile(string FileName);

		//! Allocate the memory for the images
		void AllocateImagesMemory(int NumImages);

		//! Store the images of a given file to the class storage memory
		int AppendImagesFromFile(string FileName,double ExpectedVal,int FirstIndex);

		//! Create patches from images and store them to the class storage memory
		void AppendPatches(string FileName,int NumPatches,int FirstIndex);

		//! Count the number of different expected values
		int GetNumDiffValues(int **pNumSamples=NULL,double **pValues=NULL);

		//! Copy the value parameters and allocate the dynamic data
		virtual void CopyParameters(CSamplesSet *Object,int NumSamples);

		//! Resize an image without deformation
		bool ChangeImageSize(IplImage *Source,IplImage *Destination);

		//! Change the sample with one of the patches extracted from BG files
		void ChangeSample(int Idx);

		//! Create BG Regions
		void FindNewBGRegions(int NumRegions);

#endif //USE_OPENCV			
		//! Attributes
	protected:

		//! Matrix with all the images by columns
		unsigned char *m_SamplesSet;

		//! Flag that indicates if we will use color information or not
		bool m_UseColor;	

		//! Number of channels of the stored images
		int m_NumChannels;
		
		//! Images depth.
		int m_ImgDepth;

		//! Number of stored images
		int m_NumImages;

		//! Number of positions for each image (channels, size, ...)
		int m_DataLen;

		//! Images size
		CvSize m_ImgSize;

		//! Expected value for each sample
		double *m_ExpectedValue;

		//! List of background image file names
		CStrVector m_BGFiles;

		//! Index of the last used BG file
		int m_IdxBGFile;

		//! Detector used to extract BG patches
		CDetector *m_Detector;

		//! Number of available BG Regions
		int m_AvailableBGRegions;

		//! Vector of Background Regions
		CBGRegVector m_BGRegions;
	};	

	//! Operators
	EVOLUTIVELIB_API std::ostream& operator<<(std::ostream &stream, Evolutive::CSamplesSet C);
	EVOLUTIVELIB_API std::istream& operator>>(std::istream &stream, Evolutive::CSamplesSet C);

}

#endif // __SAMPLESSET_H__
